package com.neulogistics.core.substation.api.application.command.handler;

import com.blackto.lib.mediat.unicast.IRequestHandler;
import com.neulogistics.core.substation.api.application.command.AssignCourierCommand;
import com.neulogistics.core.substation.api.application.command.ReceiptCommand;
import com.neulogistics.core.substation.api.application.integrationevent.ISubstationIntegrationEventService;
import com.neulogistics.core.substation.api.application.integrationevent.publish.ReceiptIntegrationEvent;
import com.neulogistics.core.substation.api.service.ThreadLocalService;
import com.neulogistics.core.substation.domain.exception.SubstationDomainException;
import com.neulogistics.core.substation.domain.model.aggregate.SubstationPayment;
import com.neulogistics.core.substation.domain.model.aggregate.TaskOrder;
import com.neulogistics.core.substation.domain.model.enumeration.PaymentType;
import com.neulogistics.core.substation.domain.model.enumeration.TaskStatus;
import com.neulogistics.core.substation.domain.model.enumeration.TaskType;
import com.neulogistics.core.substation.domain.repository.ISubstationPaymentRepository;
import com.neulogistics.core.substation.domain.repository.ITaskOrderRepository;
import com.neulogistics.infrastructure.cache.idservice.RedisIdUtil;
import com.neulogistics.infrastructure.common.annotation.ProduceEvent;
import com.neulogistics.infrastructure.common.serviceresult.BaseResponse;
import com.neulogistics.infrastructure.common.serviceresult.ErrorCode;
import com.neulogistics.infrastructure.common.serviceresult.ResultUtils;
import com.neulogistics.infrastructure.integrationeventlog.model.IntegrationEventConstant;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;

@Component
public class ReceiptCommandHandler implements IRequestHandler<ReceiptCommand, BaseResponse> {
    @Resource
    ITaskOrderRepository taskOrderRepository;

    @Resource
    ISubstationPaymentRepository substationPaymentRepository;

    @Resource
    ISubstationIntegrationEventService substationIntegrationEventService;

    @Resource
    RedisIdUtil redisIdUtil;

    @Resource
    private TransactionTemplate transactionTemplate;

    private final String SubstationPayment_Id_Key;

    public ReceiptCommandHandler(@Value("${spring.application.name}") String appName) {
        SubstationPayment_Id_Key = appName + ":" + "SubstationPaymentId";
    }

    @Override
    @ProduceEvent
    public BaseResponse<Boolean> handle(ReceiptCommand command) throws Exception {
        TaskOrder taskOrder = taskOrderRepository.findById(command.taskId);

        taskOrder.setCustomSatisfaction(command.customSatisfaction);
        taskOrder.setCustomEvaluation(command.customEvaluation);

        SubstationPayment payment = null;

        // 处理配送单
        if(taskOrder.getTaskType() == TaskType.Delivery_And_Crediting){
            // 生成缴款单
            Long paymentId = redisIdUtil.nextId(SubstationPayment_Id_Key);
            payment = new SubstationPayment(paymentId, PaymentType.Crediting, taskOrder.getSubstationId(),
                    taskOrder.getTaskId(), taskOrder.getCourierInfo(), taskOrder.getCustomInfo(),
                    taskOrder.getOrderInfo().getOrderItems(), taskOrder.getOrderInfo().getTotalAmount());
            // 置任务单为完成状态
            taskOrder.setTaskStatus(TaskStatus.Completed);
            taskOrder.setCompleteTime(new Date(System.currentTimeMillis()));
        }

        //处理退货单
        else if(taskOrder.getTaskType() == TaskType.Return){
            // 生成缴款单
            Long paymentId = redisIdUtil.nextId(SubstationPayment_Id_Key);
            payment = new SubstationPayment(paymentId, PaymentType.Refund, taskOrder.getSubstationId(),
                    taskOrder.getTaskId(), taskOrder.getCourierInfo(), taskOrder.getCustomInfo(),
                    taskOrder.getOrderInfo().getOrderItems(), taskOrder.getOrderInfo().getTotalAmount());

            // 置任务单为待配送状态
            taskOrder.setTaskStatus(TaskStatus.To_Be_Delivery);
        }

        // 持久化
        // 开启事务
        SubstationPayment finalPayment = payment;
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
            try {
                if(finalPayment != null){
                    substationPaymentRepository.save(finalPayment);
                }
                taskOrderRepository.save(taskOrder);

                // 发布回执填入事件
                Long eventId = redisIdUtil.nextId(IntegrationEventConstant.Integration_Event_Id_Key);
                ReceiptIntegrationEvent receiptIntegrationEvent = new ReceiptIntegrationEvent(eventId);
                receiptIntegrationEvent.setOrderId(taskOrder.getOrderInfo().getOrderId());
                Long transactionId = ThreadLocalService.transactionId.get();
                substationIntegrationEventService.addAndSaveEvent(receiptIntegrationEvent, transactionId);

            } catch (Exception e){
                // 触发回滚
                throw new RuntimeException(e.getMessage());
            }
            }
        });


        return ResultUtils.success(null);
    }
}
